package com.lehecai.core.lottery.fetcher.lotterydraw.impl.worker;

import com.lehecai.core.lottery.LotteryType;
import com.lehecai.core.lottery.fetcher.FetcherLotteryTypeMap;
import com.lehecai.core.lottery.fetcher.FetcherType;
import com.lehecai.core.lottery.fetcher.lotterydraw.LotteryDraw;
import com.lehecai.core.lottery.fetcher.lotterydraw.LotteryDrawPrizeItem;
import com.lehecai.core.util.CharsetConstant;
import com.lehecai.core.util.CoreFetcherUtils;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.*;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.tags.TableColumn;
import org.htmlparser.tags.TableRow;
import org.htmlparser.tags.TableTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 地方开奖页面中国体彩通用抓取结果
 * @author zhangzq
 *
 */
public class LocalityLotteryDrawFetchWorkerTcOfficial extends AbstractLotteryDrawFetchWorker{

	private static Map<LotteryType, String> lotteryDetailUrlMap = new HashMap<LotteryType, String>();

	protected void setLotteryDetailUrl(LotteryType lotteryType, String url) {
		synchronized (this) {
			lotteryDetailUrlMap.put(lotteryType, url);
		}
	}

	protected String getLotteryDetailUrl(LotteryType lotteryType) {
		synchronized (this) {
			return lotteryDetailUrlMap.get(lotteryType);
		}
	}

	protected String siteName = "TC_OFFICIAL";
	protected String lotteryScope = "地方开奖";
	//开奖结果所在行号  0为第一行
	private static final String BASE_URL = "http://www.lottery.gov.cn";
	private static final String RESULT_LOCALITY_URL = "http://www.lottery.gov.cn/lottery/draws/Others.aspx";

	public LocalityLotteryDrawFetchWorkerTcOfficial(LotteryType lotteryType) {
		super(lotteryType);
	}
	
	@Override
	public LotteryDraw fetchResult(String phase) {
		LotteryType lotteryType = this.getLotteryType();
		String url = RESULT_LOCALITY_URL;
		String pageInfo = "列表页面" + url;
		String logHeader = "==" + lotteryScope + "==" + siteName + "==" + pageInfo + "==抓取==" + lotteryType.getName() + "==";
		logger.info(logHeader + "开始==");

		LotteryDraw lotteryDraw = null;
		String data;
		Parser parser;
		
		data = CoreFetcherUtils.URLGet(url, null, CharsetConstant.CHARSET_GBK);
		if (data == null || data.indexOf("404 Not Found") > 0) {
			logger.error(logHeader + "data is null or 404 Not Found");
			return null;
		}
		parser = Parser.createParser(data, CharsetConstant.CHARSET_GBK);
		NodeList tableNodeList;
		try {
            tableNodeList = parser.extractAllNodesThatMatch(new TagNameFilter("table"));
		} catch (ParserException e2) {
			logger.error(logHeader + "连接错误==", e2);
			return null;
		}
        try {
            String detailLink = null;
            String lotteryName = null;
            String lotteryPhase; //页面抓取的彩期号
            if (tableNodeList != null && tableNodeList.size() > 0) {
                TableTag tableTag = (TableTag)tableNodeList.elementAt(1);
                if (tableTag == null || tableTag.getRowCount() < 1) {
                    logger.error("未获得开奖公告信息");
                    return null;
                }
                //获取含有链接td的对应href和text
                for (int i = 1; i < tableTag.getRowCount(); i++) {
                    TableColumn[] tableColumn = tableTag.getRow(i).getColumns();
                    LinkTag linkNode;
                    for (int j = 0; j < tableColumn.length; j++) {
                        //取得包含有超链接tr，获取第一个td的值作为玩法
                        if (tableColumn[j].childAt(0) instanceof LinkTag) {
                            linkNode = (LinkTag)tableColumn[j].childAt(0);
                            detailLink = linkNode.getLink().trim();
                            lotteryName = tableColumn[0].getStringText().trim();
                        }
                    }
                    if (getLotteryType().getValue() == FetcherLotteryTypeMap.getLotteryValueByKey(FetcherType.TC_OFFICIAL.getName() + lotteryName)) {
                        lotteryPhase = tableColumn[1].getStringText().trim();
                        if (lotteryPhase == null) {
                            logger.error(logHeader + "页面抓取的彩期号({})不存在,返回null==", lotteryPhase);
                            return null;
                        }
                        //处理列表页面抓取的彩期
                        //指定彩期为null，抓取列表页面的彩期数据
                        if (phase == null || phase.isEmpty()) {
                            phase = lotteryPhase;
                            //当前期可写入详细url，以便抓取对应的详细信息
                            this.setLotteryDetailUrl(lotteryType, BASE_URL + detailLink);
                        } else {
                            if (lotteryPhase.equals(phase)) {
                                phase = lotteryPhase;
                                //当前期可写入详细url，以便抓取对应的详细信息
                                this.setLotteryDetailUrl(lotteryType, BASE_URL + detailLink);
                            } else {
                                logger.error(logHeader + "指定抓取的彩期号({})与页面抓取的彩期号({})不一致,返回null==", phase, lotteryPhase);
                                return null;
                            }
                        }
                        i = tableTag.getRowCount();//结束遍历
                    }
                }
                lotteryDraw = new LotteryDraw();
                lotteryDraw.setPhase(phase);
                lotteryDraw.setLotteryType(getLotteryType());
            }
        } catch (Exception e) {
            logger.error(logHeader + "页面错误==" + e.getMessage(), e);
			return null;
        }
		if (lotteryDraw == null) {
			logger.info(logHeader + "未抓取到相关开奖结果信息,返回null");
		}
		logger.info(logHeader + "结束");
		return lotteryDraw;
	}

	@Override
	public LotteryDraw fetchResultDetail(String phase) {
        LotteryDraw lotteryDraw = null;
        try {
            String url = this.getResultDetailUrl(phase);
            if (url == null || url.isEmpty()) {
                logger.error("==" + lotteryScope + "==" + siteName + "==详细页面==抓取==" + getLotteryType().getName() + "==期号：" + phase + "==详细地址不存在，返回null");
                return null;
            }
            String pageInfo = "详细页面" + url;
            String logHeader = "==" + lotteryScope + "==" + siteName + "==" + pageInfo + "==抓取==" + getLotteryType().getName() + "==";

            logger.info(logHeader + "开始==");
            String data;
            Parser parser;

            data = CoreFetcherUtils.URLGet(url, null, CharsetConstant.CHARSET_GBK);
            if (data == null || data.indexOf("404 Not Found") > 0) {
                logger.error(logHeader + "data is null or 404 Not Found");
                return null;
            }
            parser = Parser.createParser(data, CharsetConstant.CHARSET_GBK);

            NodeList nodeList;
            try {
                NodeFilter tableFilter = new TagNameFilter("table");
                NodeFilter cssFilter = new HasAttributeFilter("width","978");
                NodeFilter filter = new AndFilter(tableFilter, cssFilter);
                nodeList = parser.extractAllNodesThatMatch(filter);
            } catch (Exception e) {
                logger.error(logHeader + "数据解析错误==" + e.getMessage(), e);
                return null;
            }
            if (nodeList == null) {
                logger.error(logHeader + "为获取的开奖详细信息");
                return null;
            }
            //抓期数,开奖时间,开奖结果,销量,奖池
            String lotteryPhase;
            String timeDraw = "";
            String result = "";
            String volumeOfSales= null;
            String jackpot = null;
            List<LotteryDrawPrizeItem> resultDetail = null;

            Parser awardTitleParser;    //获取开奖table title
            NodeList awardTitleList;
            awardTitleParser = Parser.createParser(nodeList.toHtml(), CharsetConstant.CHARSET_GBK);
            NodeFilter tableTitleFilter = new HasAttributeFilter("bgColor","#d5e7f5");
            try {
                awardTitleList = awardTitleParser.extractAllNodesThatMatch(tableTitleFilter);
            } catch (ParserException e) {
                logger.error(logHeader + "数据开奖table title解析错误==" + e.getMessage(), e);
                return null;
            }
            TableTag tableTags = (TableTag)nodeList.elementAt(0);
            TableRow[] tableRows = tableTags.getRows();
            TableColumn[] tableColumns;
            //福建22选5 浙江体彩 20选5 特殊情况
            if (awardTitleList != null && (awardTitleList.size() == 1 || awardTitleList.size() == 2)) {
                if (tableRows != null && tableRows.length > 2) {
                    //获取最新彩期的开奖详情信息 通过awardTitleList.size()来区分特殊情况
                    tableColumns = tableRows[awardTitleList.size()].getColumns();
                } else {
                    logger.error(logHeader + "解析彩票基本信息(期号,开奖时间)不存在，返回null==");
                    return null;
                }
                if (tableColumns != null && tableColumns.length >= 9) {
                    //彩期
                    lotteryPhase = trimAll(tableColumns[0].toPlainTextString());
                    if (lotteryPhase == null) {
                        logger.error(logHeader + "页面抓取的彩期号({})不存在,返回null==", lotteryPhase);
                        return null;
                    }
                    //处理列表页面抓取的彩期
                    if (phase == null || phase.isEmpty()) {
                        phase = lotteryPhase;
                    } else {
                        if (lotteryPhase.equals(phase)) {
                            phase = lotteryPhase;
                        } else {
                            logger.error(logHeader + "指定抓取的彩期号({})与页面抓取的彩期号({})不一致,返回null==", phase, lotteryPhase);
                            return null;
                        }
                    }
                    //开奖时间 取最后一项
                    timeDraw = trimAll(tableColumns[tableColumns.length - 1].toPlainTextString());
                    //开奖结果
                    String resultTemp  = tableColumns[1].toPlainTextString().trim().replace("  ", "").replace("+", " ").replace("  ", " ");
                    String[] resultArray = resultTemp.split(" ");
                    result = CoreFetcherUtils.mergeStringArray(resultArray, ",");
                    //开奖详情
                    TableColumn[] titleTableColumns = tableRows[0].getColumns();
                    resultDetail = lotteryDrawPrizeItemList(titleTableColumns, tableColumns, awardTitleList.size(), logHeader);
                    if (resultDetail == null) {
                        logger.error(logHeader+"解析彩票奖项明细信息不存在，返回null==");
                        return null;
                    }
                    //销量
                    //奖池
                }
            }
            lotteryDraw = new LotteryDraw();
            lotteryDraw.setPhase(phase);
            lotteryDraw.setResult(result);
            lotteryDraw.setTimeDraw(CoreFetcherUtils.formatTimeDraw(timeDraw));
            lotteryDraw.setJackpot(jackpot);
            lotteryDraw.setVolumeOfSales(volumeOfSales);
            lotteryDraw.setLotteryType(getLotteryType());
            lotteryDraw.setResultDetail(resultDetail);
            if (lotteryDraw == null) {
                logger.info(logHeader + "未抓取到相关开奖结果信息,返回null==");
            }
            logger.info(logHeader + "结束==");
        } catch (Exception e) {
            logger.error("解析开奖详情页面出现异常");
            logger.error(e.getMessage(), e);
        }
		return lotteryDraw;
	}

	@Override
	protected String getResultDetailUrl(String phase) {
		return this.getLotteryDetailUrl(this.getLotteryType());
	}

	@Override
	protected String getResultUrl(String phase) {
		return null;
	}

    /**
     * 各种奖项详情
     * */
    private List<LotteryDrawPrizeItem> lotteryDrawPrizeItemList (TableColumn[] titleTableColumns, TableColumn[] tableColumns, int awardTitleListLength, String logHeader) {
        List<LotteryDrawPrizeItem> list = new ArrayList<LotteryDrawPrizeItem>();
        String prizeItemName;//奖项名称
        String winningCount;
        String prizeAmount;
        try {
            if (awardTitleListLength == 1) {
                for (int k = 2; k < titleTableColumns.length - 1; k++) {
                    LotteryDrawPrizeItem lotteryDrawPrizeItem = new LotteryDrawPrizeItem();
                    prizeItemName = trimAll(titleTableColumns[k].toPlainTextString());
                    String winStr = tableColumns[k].toPlainTextString();
                    winningCount = trimAll(winStr.substring(0,winStr.indexOf("注")));
                    prizeAmount = trimAll(winStr.substring(winStr.indexOf("注") + 1, winStr.indexOf("元")));
                    lotteryDrawPrizeItem.setName(prizeItemName);
                    lotteryDrawPrizeItem.setWinningCount(winningCount);
                    lotteryDrawPrizeItem.setPrizeAmount(prizeAmount);
                    list.add(lotteryDrawPrizeItem);
                }
            } else if (awardTitleListLength == 2) {
                int temp = 3;
                for (int k = 3; k < titleTableColumns.length - 1; k++) {
                    LotteryDrawPrizeItem lotteryDrawPrizeItem = new LotteryDrawPrizeItem();
                    prizeItemName = trimAll(titleTableColumns[k].toPlainTextString());
                    winningCount = trimAll(tableColumns[temp].toPlainTextString()).replace("注", "");
                    prizeAmount = trimAll(tableColumns[++temp].toPlainTextString()).replace("元", "");
                    lotteryDrawPrizeItem.setName(prizeItemName);
                    lotteryDrawPrizeItem.setWinningCount(winningCount);
                    lotteryDrawPrizeItem.setPrizeAmount(prizeAmount);
                    ++temp;
                    list.add(lotteryDrawPrizeItem);
                }
            }
        } catch (Exception e) {
            logger.error(logHeader + "获取奖项明细详情出现异常");
            return null;
        }
        return list;
    }

    /**
     * 替换字符串的各种特殊符号
     * @param str
     * @return
     */
    private static String trimAll(String str) {
        if (str != null && !str.equals("")) {
            str = str.replaceAll(" ", "");
            str = str.replaceAll("　", "");
            str = str.replaceAll("&nbsp;", "");
            str = str.replaceAll("。", "");
            str = str.replaceAll("：", "");
            str = str.replaceAll(":", "");
            str = str.replaceAll(",", "");
            str = str.replaceAll("\t", "");
        }
        return str;
    }

    public static void main(String[] args) {
        String phase = "14107";
        LocalityLotteryDrawFetchWorkerTcOfficial localityLotteryDrawFetchWorkerTcOfficial = new LocalityLotteryDrawFetchWorkerTcOfficial(LotteryType.A_JS7);//A_JS7/BJTC33X7/A_HN4/A_FJ31/A_ZJ20/A_FJ22/A_FJ36/A_HLJ6
        localityLotteryDrawFetchWorkerTcOfficial.fetchResult(phase);
        localityLotteryDrawFetchWorkerTcOfficial.fetchResultDetail(phase);
    }

}
